package com.service.admin.merchant.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.service.admin.admin.dto.LoginUserSession;
import com.service.admin.merchant.controller.rep.CreditLineStatementPageRep;
import com.service.admin.merchant.controller.rep.MemberCreditLineRep;
import com.service.admin.merchant.controller.req.CreditLineUpdateBalanceReq;
import com.service.admin.merchant.service.MerchantCreditLineService;
import com.service.admin.merchant.service.MerchantCreditLineStatementService;
import com.service.admin.merchant.service.MerchantService;
import com.service.admin.support.SessionUtil;
import com.service.core.exception.CommonException;
import com.service.core.rest.request.PageRequest;
import com.service.core.rest.response.CommonPageRep;
import com.service.dao.dto.MerchantCreditLineChange;
import com.service.dao.enums.CoinsEnum;
import com.service.dao.enums.MerchantEnums;
import com.service.dao.enums.StatementTypeEnum;
import com.service.dao.model.Merchant;
import com.service.dao.model.MerchantCreditLine;
import com.service.dao.model.MerchantCreditLineStatement;
import com.service.utility.modelmapper.ModelMapperUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import com.service.dao.mapper.MerchantCreditLineMapper;
import org.springframework.util.ObjectUtils;


@Service("merchantCreditLineService")
public class MerchantCreditLineServiceImpl extends ServiceImpl<MerchantCreditLineMapper, MerchantCreditLine> implements MerchantCreditLineService {

    @Autowired
    private SessionUtil sessionUtil;

    @Autowired
    private MerchantService merchantService;

    @Autowired
    private MerchantCreditLineStatementService statementService;

    @Override
    public List<MemberCreditLineRep> merchantCreditLine(Integer merchantId) {

        List<MerchantCreditLine> merchantCreditLine = list(new QueryWrapper<MerchantCreditLine>()
                .lambda().eq(MerchantCreditLine::getMerchantId, merchantId));

        if (ObjectUtils.isEmpty(merchantCreditLine)) {
            throw new CommonException("暂无授信额度", "merchant_credit_line_exception_empty");
        }
        return merchantCreditLine.stream().map(item -> ModelMapperUtil.map(item, MemberCreditLineRep.class))
                .collect(Collectors.toList());
    }

    @Override
    public CommonPageRep<CreditLineStatementPageRep> pageStatement(Integer merchantId, CoinsEnum coins, PageRequest pageRequest) {

        MerchantCreditLine merchantCreditLine = getOne(new QueryWrapper<MerchantCreditLine>()
                .lambda().eq(MerchantCreditLine::getMerchantId, merchantId)
                .eq(MerchantCreditLine::getCoinsId, coins.getCode()));

        if (ObjectUtils.isEmpty(merchantCreditLine)) {
            throw new CommonException("暂无授信额度", "merchant_credit_line_exception_empty");
        }

        return statementService.pageStatement(coins, merchantCreditLine.getId(), pageRequest);
    }


    @Override
    public void updateBalance(CreditLineUpdateBalanceReq updateBalanceReq) {

        Merchant merchant = merchantService.getById(updateBalanceReq.getMerchantId());
        if (ObjectUtils.isEmpty(merchant)) {
            throw new CommonException("此商家不存在");
        }

        if (!(ObjectUtils.nullSafeEquals(merchant.getMerchantStatus(), MerchantEnums.Status.in_business.getCode())
                || ObjectUtils.nullSafeEquals(merchant.getMerchantStatus(), MerchantEnums.Status.rest.getCode()))) {
            throw new CommonException("此商家暂未通过审核或者已冻结,不能修改授信额度");
        }

        MerchantCreditLine creditLine = getCreditLine(updateBalanceReq.getMerchantId(), updateBalanceReq.getCoins().getName());
        if (ObjectUtils.isEmpty(creditLine)) {

            creditLine = MerchantCreditLine.builder()
                    .memberId(merchant.getMemberId())
                    .merchantId(merchant.getId())
                    .creditNum(BigDecimal.ZERO)
                    .residueNum(BigDecimal.ZERO)
                    .coinsId(updateBalanceReq.getCoins().getCode())
                    .coinsName(updateBalanceReq.getCoins().getName())
                    .createTime(new Date())
                    .build();

            save(creditLine);
        }

        if (creditLine.getCreditNum().compareTo(updateBalanceReq.getCreditNum()) == 0) {
            throw new CommonException("暂未变更授信额度");
        }

        BigDecimal useNum = creditLine.getCreditNum().subtract(creditLine.getResidueNum());

        if (useNum.compareTo(updateBalanceReq.getCreditNum()) > 0) {
            throw new CommonException("最低变更授信额度为:" + useNum);
        }
        BigDecimal changeNum;
        BigDecimal currentResidueNum = updateBalanceReq.getCreditNum().subtract(useNum);
        StatementTypeEnum statementType;
        if(creditLine.getCreditNum().compareTo(updateBalanceReq.getCreditNum()) > 0){
            changeNum = creditLine.getResidueNum().subtract(currentResidueNum);
            statementType = StatementTypeEnum.REDUCE_BALANCE;

        }else{
            changeNum = currentResidueNum.subtract(creditLine.getResidueNum());
            statementType = StatementTypeEnum.ADD_BALANCE;
        }

        LoginUserSession userSession = sessionUtil.getUser();

        MerchantCreditLineChange creditLineChange = MerchantCreditLineChange.builder()
                .coinsId(updateBalanceReq.getCoins().getCode())
                .coinsName(updateBalanceReq.getCoins().getName())
                .merchantId(updateBalanceReq.getMerchantId())
                .statementType(statementType)
                .changeNum(changeNum)
                .remark(statementType.getMsg()+",操作人:{id:"+userSession.getId()+",loginName:"+userSession.getLoginName()+"}")
                .build();

        updateCreditLineBalance(creditLine, creditLineChange);
    }

    public void updateCreditLineBalance(MerchantCreditLine creditLine, MerchantCreditLineChange creditLineChange) {

        creditLineChange.getStatementType().doOptStore(creditLine, creditLineChange.getChangeNum());
        BigDecimal residueNum = creditLine.getResidueNum();

        MerchantCreditLineStatement statement = MerchantCreditLineStatement.builder()
                .changeNum(creditLineChange.getChangeNum())
                .coinsId(creditLineChange.getCoinsId())
                .coinsName(creditLineChange.getCoinsName())
                .merchantId(creditLine.getMerchantId())
                .creditLineId(creditLine.getId())
                .orderId(creditLineChange.getOrderId())
                .remark(creditLineChange.getRemark())
                .residueNum(residueNum)
                .creditNum(creditLine.getCreditNum())
                .statementType(creditLineChange.getStatementType().getCode())
                .createTime(new Date())
                .build();

        statementService.save(statement);

        updateById(MerchantCreditLine.builder().creditNum(creditLine.getCreditNum())
                .residueNum(creditLine.getResidueNum()).id(creditLine.getId()).build());

    }

    public MerchantCreditLine getCreditLine(Integer merchantId, String coinsName) {
        return getOne(new QueryWrapper<MerchantCreditLine>().lambda()
                .eq(MerchantCreditLine::getMerchantId, merchantId)
                .eq(MerchantCreditLine::getCoinsName, coinsName));

    }


}
